﻿// See https://aka.ms/new-console-template for more information

using System.Reflection;
using Reflection;

Console.WriteLine("Hello, World!");

var orderType = typeof(Order);
var typeType = typeof(Type);

var order = new Order();
var orderTypeFromInstance = order.GetType();

// typeof(Order) == order.GetType() // true

var service = ServiceFactory.Produce();
if (service.GetType() == typeof(SimpleService)) {
    // ...
}

var orderInstance = new Order();
var orderTypeInfo = typeof(Order);
var anotherOrderInstance = (Order)Activator.CreateInstance(orderTypeInfo);

var orderTypeInfoFromName =
    Assembly.GetExecutingAssembly().GetType("Reflection.Order");
var orderInstanceFromName =
    (Order)Activator.CreateInstance(orderTypeInfoFromName);

var iServiceType =
    Assembly.GetExecutingAssembly().GetType("Reflection.IService");
// 也可为 var iServiceType = typeof(IService);
var simpleServiceType = Assembly.GetExecutingAssembly()
    .GetType("Reflection.SimpleService");
// 也可为 var simpleServiceType = typeof(SimpleService);
Console.WriteLine(simpleServiceType.IsAssignableTo(iServiceType));

Console.WriteLine(simpleServiceType.BaseType);
foreach (var @interface in simpleServiceType.GetInterfaces()) {
    Console.WriteLine(@interface);
}

// var types = Assembly.GetExecutingAssembly().GetTypes();
// var subTypesOfIService = 
//     types.Where(p => p.IsAssignableTo(iServiceType));

var subTypesOfIService = Assembly.GetExecutingAssembly().GetTypes()
    .Where(p => p.IsAssignableTo(iServiceType));

foreach (var subType in subTypesOfIService) {
    Console.WriteLine(subType);
}
/* 输出
 * Reflection.IService
 * Reflection.SimpleService
 * Reflection.ComplexService
 */

var someObjectType = typeof(SomeObject);
var someFunctionInformation =
    someObjectType.GetMethod(nameof(SomeObject.SomeFunction));

Console.WriteLine(someFunctionInformation.IsPublic);
Console.WriteLine(someFunctionInformation.ReturnType);
Console.WriteLine(someFunctionInformation.Name);
Console.WriteLine(someFunctionInformation.GetParameters().Length);
Console.WriteLine(someFunctionInformation.GetParameters()[0].ParameterType);
Console.WriteLine(someFunctionInformation.GetParameters()[0].Name);

var someObject = new SomeObject();
var ret =
    (string)someFunctionInformation.Invoke(someObject, new object?[] { 500 });
Console.WriteLine(string.IsNullOrEmpty(ret));

var instance = new ComplexClass(1, new SimpleService());

var complexClassType = typeof(ComplexClass);
var constructors = complexClassType.GetConstructors();
var firstConstructor = constructors.First();
var constructorParameters = 
    firstConstructor.GetParameters();
Console.WriteLine(constructorParameters.Length);
Console.WriteLine(constructorParameters[0].ParameterType);
Console.WriteLine(constructorParameters[1].ParameterType);
var complexClassInstance =
    (ComplexClass) firstConstructor.Invoke(
        new object[] { 1, new SimpleService() });